//animation example 1
//uses the animation module to read some animations and graphics and show them in a timer loop
#include "..\..\..\axl_animations.h"
#include <time.h>
using namespace AXL_Projects;
using namespace ol;

int current=0;
//stuff for the timers
volatile int xframe_count;
volatile int fps;
volatile int xgame_time;

//main game variables
static AnimationLibrary* GameLibrary;		//library of available animations
											//useful for when we want to use the animation stuff like timers, etc.
static Bitmap* LogoAnimationSimple;			//grabbed directly without creating any new object and new animation stuff is available
static Animation* SpawnedAnimations[40];	//for showing lots of them
static Animation* MainAnimation=NULL;
static Animation* CollisionAnimation=NULL;
static Animation* LogoAnimation=NULL;

static TextRenderer* courierfont=NULL;

//show the main options available inside the animation module
void DoMenu(int speed)
{
	courierfont->Print("1 Change to stop at end",0,10);
	courierfont->Print("2 Change to repeat ping pong",0,20);
	courierfont->Print("3 Change to repeat from start",0,30);
	courierfont->Print("4 Change to ping pong once",0,40);
	courierfont->Print("5 Change to there back and there again",0,50);
	courierfont->Print("6 Pause",0,60);
	courierfont->Print("7 Resume",0,70);
	courierfont->Print("8 Set To Auto Animation",0,80);
	courierfont->Print("9 Set To Manual Animation - press SPACE for next frame when set",0,90);
	courierfont->Print("0 Reset to normal",0,100);
	courierfont->Print("B Fade-out in 5 seconds (animation stays on and it works just as normal)",0,120);
	courierfont->Print("C Fade-in in 5 seconds (assumes at full hiddne - if not will take less time)",0,130);
	courierfont->Print("+ Increase speed by 10ms",0,140);
	courierfont->Print("- Decrease speed by 10ms",0,150);
	courierfont->Print("F1 to F4 set countdown timer to random number of seconds",0,160);
	courierfont->Print("ESC to quit",0,170);
	courierfont->SetColor(Rgba(255,100,255));
	courierfont->Print("Is End Animation Reached: "+ToString(MainAnimation->ReadOnly_EndReached),0,180);
	courierfont->Print("Countdown Readed : fade ("+ToString(MainAnimation->ReadOnly_Timers[0])+"), C1 ("+ToString(MainAnimation->ReadOnly_Timers[1])+"), C2("+ToString(MainAnimation->ReadOnly_Timers[2])+"), C3("+ToString(MainAnimation->ReadOnly_Timers[3])+"), C4("+ToString(MainAnimation->ReadOnly_Timers[4]),0,190);
	courierfont->Print("Countdown value  : fade ("+ToString(MainAnimation->ReadOnly_TimersCounter[0])+"), C1 ("+ToString(MainAnimation->ReadOnly_TimersCounter[1])+"), C2("+ToString(MainAnimation->ReadOnly_TimersCounter[2])+"), C3("+ToString(MainAnimation->ReadOnly_TimersCounter[3])+"), C4("+ToString(MainAnimation->ReadOnly_TimersCounter[4]),0,200);
	courierfont->Print("FPS: "+ToString(fps)+", Current Frame Speed Milliseconds: "+ToString(speed),0,210);
	courierfont->SetColor(Rgba::WHITE);
	courierfont->Print("s Change animation sprite",200,230);
	courierfont->Print("t Spawn lots of animations",200,240);
	courierfont->Print("Collision",501,211);
	courierfont->Print("Use Cursors",501,468);
}

//this example is using a standard timer based FPS loop to keep program running smoothly and to time
//called every second to store the fps for display only
void xFpsHandler()
{
 //called every 1000 milliseconds
 fps=xframe_count; //set fps to display to user
 xframe_count=0;   //reset the count for the next loop
}
END_OF_FUNCTION(fps_handler);

//timer for the game loop for keeping fps called every required FPS value
void xgame_timer()
{
	xgame_time++;
}
END_OF_FUNCTION(xgame_timer);

//set up allegro
bool Init()
{
	if(!Setup::SetupProgram())
		return false;
	if(!Setup::SetupScreen(640,480,false))
		return false;

	Settings::SetAntialiasing(true);
	courierfont=new TextRenderer("cour.ttf",10,10,Rgba::WHITE);
	if(!courierfont->IsValid())
	{
		delete courierfont;
		return false;
	}
	//fps timer and other timer locks
	fps=xframe_count=0;
	LOCK_VARIABLE(fps);
	LOCK_VARIABLE(xframe_count);
	LOCK_FUNCTION(xFpsHandler);
	LOCK_FUNCTION(xgame_timer);
	install_int(xFpsHandler,1000);
	install_int_ex(xgame_timer,BPS_TO_TIMER(60));

	return true;
}

//loop for animation
int main(void)
{
	bool done=false;
	bool draw=false;
	bool CanMove=true;
	bool FirstSprite=true;
	bool ShowSpawned=false;
	int CollisionTest=0;

	int w,h,logow,logoh;
	int coll_x=503;
	int coll_y=218;
	int speed;
	int keypress;


	srand ( time(NULL) );
	xgame_time=1;
	AnimationLibrary::LogEntry("start",true,"test.log");	//log somestuff

	if (!Init())
	{
		allegro_message("Failed init. see logs");
		return 1;
	}
	SpawnedAnimations[0]=NULL;	//quickly show not set up yet

	AnimationLibrary::LogEntry("initialised",false,"test.log");

	//create an animation repository and load the animations
	GameLibrary=new AnimationLibrary("animations_single_png.xml");
	if(GameLibrary->LoadError)
	{
		AnimationLibrary::LogEntry("Failed to load XML. Check it is valid",false,"test.log");
		delete GameLibrary;
		return 1;
	}
	
	//debugging information
	//GameLibrary->draw();
	GameLibrary->DebugData();

	//get animation via a string. the normal way to retrieve an animation
	MainAnimation=new Animation(GameLibrary,"fuel");
	CollisionAnimation=new Animation(GameLibrary,"ufo");
	
	//get animation the via the library just to show how it is done, this is faster than the above method if speed is critical
	// and you aren't pre-creating the animations
	AnimationLibraryFrames* af=GameLibrary->GetAnimation("logo");
	LogoAnimation=new Animation(GameLibrary,af);

	//if all we want is to grab a graphic and do not need an animation then we do not need to create a full animation object
	//instead this function gets the first (or only) graphic for the entry in the XML called logo and returns a BITMAP*
	LogoAnimationSimple=GameLibrary->GetFirstGraphic("logo");

	//get sizes and speed for displaying later
	MainAnimation->GetStandardDimensions(&w,&h);
	LogoAnimation->GetStandardDimensions(&logow,&logoh);
	speed=MainAnimation->GetCurrentSpeedMS();

	Rect rectmain(500,210,139,269);

MainAnimation->ReadOnly_CurrentItem->BlitStretched(100,240,w*2,h*2);
Canvas::Refresh();
readkey();

	//main timer loop
	//each keypress does what is says
	do {
		while(xgame_time!=0) 
		{
			draw=false;
			CanMove=false;	//manual mode only
			if(keypressed())
			{
				keypress=readkey()>>8;
				switch(keypress)
				{
					//keys 1-5 change the way the animation loops
				case KEY_1:
					MainAnimation->SetNewLoopType(LOOP_ONCE);
					break;
				case KEY_2:
					MainAnimation->SetNewLoopType(LOOP_REVERSEREPEAT);
					break;
				case KEY_3:
					MainAnimation->SetNewLoopType(LOOP_START);
					break;
				case KEY_4:
					MainAnimation->SetNewLoopType(LOOP_REVERSEONCE);
					break;
				case KEY_5:
					MainAnimation->SetNewLoopType(LOOP_REVERSEBACK);
					break;
				//pause/resume animations
				case KEY_6:
					MainAnimation->Pause();
					break;
				case KEY_7:
					MainAnimation->Resume();
					break;
				//automatic animation or single stepping
				case KEY_8:
					MainAnimation->SetAutoMode(true);
					break;
				case KEY_9:
					MainAnimation->SetAutoMode(false);
					break;
				//reset all values to what they were on loading
				case KEY_0:
					MainAnimation->Reset();
					break;
				//swap animations
				case KEY_S:
					if(FirstSprite) MainAnimation->SetNewAnimation("ufo");
					else MainAnimation->SetNewAnimation("fuel");
					FirstSprite=!FirstSprite;
					break;
				//create lots of animations
				case KEY_T:
					if(!SpawnedAnimations[0])
					{
						AnimationLibrary::LogEntry("spawning",false,"test.log");
						for(int i=0;i<40;++i)
						{
							if(i%2) SpawnedAnimations[i]=new Animation(GameLibrary,"fuel");
							else SpawnedAnimations[i]=new Animation(GameLibrary,"ufo");
							SpawnedAnimations[i]->SetNewSpeedMS(rand()%150+50);
						}
					}
					ShowSpawned=true;
					break;
				//fading. if fblend is initialised, then fading will use that
				case KEY_B:
					MainAnimation->FadeOut(5000,true,makecol(0,0,0));
					break;
				case KEY_C:
					MainAnimation->FadeIn(5000,true,makecol(0,0,0));
					break;
				case KEY_SPACE:
					CanMove=true;
					break;
				case KEY_MINUS:
					speed-=10;
					MainAnimation->SetNewSpeedMS(speed);
					break;
				case KEY_EQUALS:
					speed+=10;
					MainAnimation->SetNewSpeedMS(speed);
					break;
				//custom countdown values
				case KEY_F1:
					MainAnimation->SetCustomCountDown(1,5000);
					break;
				case KEY_F2:
					MainAnimation->SetCustomCountDown(2,(rand()%5+5)*1000);
					break;
				case KEY_F3:
					MainAnimation->SetCustomCountDown(3,(rand()%5+5)*1000);
					break;
				case KEY_F4:
					MainAnimation->SetCustomCountDown(4,(rand()%5+5)*1000);
					break;
				//movement for collision system shown in screen
				case KEY_UP:
					if(coll_y>235) coll_y--;
					break;
				case KEY_DOWN:
					if(coll_y<460) coll_y++;
					break;
				case KEY_LEFT:
					if(coll_x>500) coll_x--;
					break;
				case KEY_RIGHT:
					if(coll_x<600) coll_x++;
					break;
				case KEY_ESC:
					done=true;
					break;
				}
				clear_keybuf();
			}

			//collision test
			//returns 1 for bounding box or 2 for pixel perfect
			CollisionTest=CollisionAnimation->CheckCollision(coll_x,coll_y, MainAnimation->ReadOnly_CurrentCollisionPoly, 570,270);

			//main display sprite
			if(done==false) 
			{
				//this is to be called every frame and updates the animation and all associated data, e.g. countdown timers, fades, etc.
				if(MainAnimation->GetAutoMode()) MainAnimation->NextMove();
				else
				{	
					//if manual mode then do full move this frame if space pressed
					//otherwise just update the timers for the fade/countdown as we still
					//need these to work
					if(CanMove) MainAnimation->NextMove();
					else MainAnimation->ManualTimerUpdate();
				}
				draw=true;
			}

			xgame_time--;
		}
		//should exit loop every FRAMERATE/second second if on time
		//update display if frame has been drawn
		//if not then system is too fast so don't do anything
		if(draw) 
		{
			//function call order is z order
			Canvas::Fill(Rgba::BLACK);
			rectmain.DrawOutline(Rgba::RED);
			DoMenu(MainAnimation->GetCurrentSpeedMS());
			LogoAnimation->ReadOnly_CurrentItem->Blit(400,0);
			LogoAnimationSimple->Blit(400,70);
			MainAnimation->ReadOnly_CurrentItem->BlitStretched(100,240,w*2,h*2);

			//our stuff for collision
			MainAnimation->ReadOnly_CurrentItem->Blit(570,270);
			CollisionAnimation->ReadOnly_CurrentItem->Blit(coll_x,coll_y);
			if(CollisionTest==2)
			{
				courierfont->Print("Collision!",501,221);
				//rectcollision.MoveTo(Vec2D(coll_x,coll_y));
				//rectcollision.DrawOutline(Rgba::GREEN);
				//rectsprite.MoveTo(Vec2D(570,270));
				//rectsprite.DrawOutline(Rgba::BLUE);
				CollisionAnimation->ReadOnly_CurrentCollisionPoly->MoveTo(Vec2D(coll_x,coll_y));
				CollisionAnimation->ReadOnly_CurrentCollisionPoly->DrawOutline(Rgba::GREEN);
				MainAnimation->ReadOnly_CurrentCollisionPoly->MoveTo(Vec2D(570,270));
				MainAnimation->ReadOnly_CurrentCollisionPoly->DrawOutline(Rgba::BLUE);
			}

			//spawned - pressed T
			if(ShowSpawned)
			{
				for(int j=0;j<4;++j)
				{
					for(int k=0;k<10;++k)
					{
						SpawnedAnimations[j*10+k]->NextMove();
						SpawnedAnimations[j*10+k]->ReadOnly_CurrentItem->Blit(k*50,300+j*50);
					}
				}
			}

			Canvas::Refresh();
			xframe_count++; //update every drawn screen - should match fps which is required FPS or less, cannot be higher
			draw=false;
		}

	} while(done==false);

	if(courierfont)
		delete courierfont;

	//we created these, so we delete them
	for(int l=0;l<40;++l)
		delete SpawnedAnimations[l];

	//we created these, so we delete them
	delete MainAnimation;
	delete CollisionAnimation;

	//this will destroy the library, unload all loaded graphics and free up all memory
	delete GameLibrary;

	remove_int(xFpsHandler);
	remove_int(xgame_timer);

	//allegro_exit();

	return 0;
}
END_OF_MAIN()

//just in case allegro_core is included for logging, need this function
void GameLoop() {}



/*
void xFpsHandler()
{
 //called every 1000 milliseconds
 fps=xframe_count; //set fps to display to user
 xframe_count=0;   //reset the count for the next loop
}
END_OF_FUNCTION(fps_handler);

//timer for the game loop for keeping fps called every required FPS value
void xgame_timer()
{
	xgame_time++;
}
END_OF_FUNCTION(xgame_timer);

//set up allegro
bool Init()
{
	if(!Setup::SetupProgram())
		return false;
	if(!Setup::SetupScreen(640,480,true))
		return false;
	courierfont=new TextRenderer("cour.ttf",20,20,Rgba::WHITE);
	if(!courierfont->IsValid())
	{
		delete courierfont;
		return false;
	}

	//fps timer and other timer locks
	fps=xframe_count=0;
	LOCK_VARIABLE(fps);
	LOCK_VARIABLE(xframe_count);
	LOCK_FUNCTION(xFpsHandler);
	LOCK_FUNCTION(xgame_timer);
	install_int(xFpsHandler,1000);
	install_int_ex(xgame_timer,BPS_TO_TIMER(60));

	return true;
}

//loop for animation
int main(void)
{
	bool done=false;
	bool draw=false;
	bool CanMove=true;
	bool FirstSprite=true;
	bool ShowSpawned=false;
	int CollisionTest=0;

	int w,h,logow,logoh;
	int coll_x=503;
	int coll_y=218;
	int speed;
	int keypress;


	srand ( time(NULL) );
	xgame_time=1;
	AnimationLibrary::LogEntry("start",true,"test.log");	//log somestuff

	if (!Init())
	{
		allegro_message("Failed init. see logs");
		return 1;
	}
	SpawnedAnimations[0]=NULL;	//quickly show not set up yet

	AnimationLibrary::LogEntry("initialised",false,"test.log");

	//create an animation repository and load the animations
	GameLibrary=new AnimationLibrary();
	if(GameLibrary->LoadError)
	{
		AnimationLibrary::LogEntry("Failed to load XML. Check it is valid",false,"test.log");
		delete GameLibrary;
		return 1;
	}
	current=25000;
for(int k=0;k<current;k++)
{
		SpawnedAnimations[k]=new Animation(GameLibrary,"fuel");
		SpawnedAnimations[k]->SetNewSpeedMS(rand()%150+50);
}
	//main timer loop
	//each keypress does what is says
	do {
		while(xgame_time!=0) 
		{
			draw=false;
			CanMove=false;	//manual mode only
			if(keypressed())
			{
				keypress=readkey()>>8;
				switch(keypress)
				{
				//create lots of animations
				case KEY_T:
					if(!SpawnedAnimations[current])
					{
							SpawnedAnimations[current]=new Animation(GameLibrary,"fuel");
							SpawnedAnimations[current]->SetNewSpeedMS(rand()%150+50);
					}
					current++;
					ShowSpawned=true;
					break;
				case KEY_ESC:
					done=true;
					break;
				}
				clear_keybuf();
			}

			//main display sprite
			if(done==false) 
			{
    			if(current>0)
    			{
    					for(int k=0;k<current;++k)
    					{
    						SpawnedAnimations[k]->NextMove();
    					}
    			}
				draw=true;
			}

			xgame_time--;
		}
		//should exit loop every FRAMERATE/second second if on time
		//update display if frame has been drawn
		//if not then system is too fast so don't do anything
		if(draw) 
		{
                 Canvas::Fill(Rgba::BLACK);
			//spawned - pressed T
			if(current>0)
			{
//Bitmap::StartFastBlitting(); 
					for(int k=0;k<current;++k)
					{
						SpawnedAnimations[k]->ReadOnly_CurrentItem->Blit(rand()%6000,rand()%400);
					}
//Bitmap::FinishFastBlitting();
			}
	      courierfont->Print("sprites: "+ToString(current)+" fps: "+ToString(fps),0,20);

			Canvas::Refresh();
			xframe_count++; //update every drawn screen - should match fps which is required FPS or less, cannot be higher
			draw=false;
		}

	} while(done==false);

	//we created these, so we delete them
	for(int l=0;l<current;++l)
		delete SpawnedAnimations[l];

	//this will destroy the library, unload all loaded graphics and free up all memory
	delete GameLibrary;
 
    if(courierfont) delete courierfont;
    
	remove_int(xFpsHandler);
	remove_int(xgame_timer);

	//allegro_exit();

	return 0;
}

END_OF_MAIN()

//just in case allegro_core is included for logging, need this function
void GameLoop() {}

*/
